
# -----------------------------------------------------------------------------
# script.py
#
# A simple script engine with variables.   
# Lex and Yacc"
# -----------------------------------------------------------------------------

import sys
sys.path.insert(0,"../..")

import ply.lex as lex
import ply.yacc as yacc
import os
import copy

if sys.version_info[0] >= 3:
    raw_input = input

class DATAITEM:
    def __init__(self, value, date):
        self.value = value
        self.date = date

    def __repr__(self):
        return str(self.value)

    def __str__(self):
        return str(self.value)
        

class MYDATA:
    data = []
    v = 0
    isvector = 0

    def __str__(self):
        if self.isvector == 0:
            return str(self.v)
        else:
            return str(self.data)

    def __repr__(self):
        if self.isvector == 0:
            return str(self.v)
        else:
            return str(self.data)
    
    def __add__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
                d.data.append(DATAITEM(other.v+self.data[i].value, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = other.v + self.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(other.data[i].value+self.v, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(other.data[i].value+self.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __sub__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
                d.data.append(DATAITEM(self.data[i].value-other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v - other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.v-other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.data[i].value - other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __mul__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
                #d.data.append(self.data[i]*other.v)
                d.data.append(DATAITEM(self.data[i].value*other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v * other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                #d.data.append(self.v * other.data[i])
                d.data.append(DATAITEM(self.v*other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                #d.data.append(self.data[i] * other.data[i])
                d.data.append(DATAITEM(self.data[i].value * other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __div__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
                try:
                    d.data.append(DATAITEM(self.data[i].value/other.v, self.data[i].date))
                except ZeroDivisionError:
                    d.data.append(DATAITEM(None, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            try:
                d.v = self.v / other.v
            except ZeroDivisionError:
                d.v = None
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                try:
                    d.data.append(DATAITEM(self.v/other.data[i].value, other.data[i].date))
                except ZeroDivisionError:
                    d.data.append(DATAITEM(None, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                try:
                    #d.data.append(self.data[i] / other.data[i])
                    d.data.append(DATAITEM(self.data[i].value / other.data[i].value, self.data[i].date))
                except ZeroDivisionError:
                    d.data.append(DATAITEM(None, self.data[i].date))
            d.isvector = 1
            return d

    def __gt__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
                #d.data.append(self.data[i]>other.v)
                d.data.append(DATAITEM(self.data[i].value>other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v > other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.v>other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.data[i].value > other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __ge__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
               d.data.append(DATAITEM(self.data[i].value>=other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v >= other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.v>=other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.data[i].value >= other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __lt__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
               d.data.append(DATAITEM(self.data[i].value<other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v < other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.v<other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.data[i].value < other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __le__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
               d.data.append(DATAITEM(self.data[i].value<=other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v <= other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.v<=other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                d.data.append(DATAITEM(self.data[i].value <= other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __eq__(self, other):
        d = MYDATA()
        d.data = []
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
               #d.data.append(self.data[i]==other.v)
                d.data.append(DATAITEM(self.data[i].value==other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v == other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                #d.data.append(self.v == other.data[i])
                d.data.append(DATAITEM(self.v==other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                #d.data.append(self.data[i] == other.data[i])
                d.data.append(DATAITEM(self.data[i].value == other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d

    def __ne__(self, other):
        d = MYDATA()
        d.data = []
        #print self, other
        if other.isvector == 0 and self.isvector == 1:
            for i in range(0, len(self.data)):
               d.data.append(DATAITEM(self.data[i].value!=other.v, self.data[i].date))
            d.isvector = 1
            return d
        elif other.isvector == 0 and self.isvector == 0:
            d.isvector = 0
            d.v = self.v != other.v
            return d
        elif other.isvector == 1 and self.isvector == 0:
            for i in range(0, len(other.data)):
                #d.data.append(self.v != other.data[i])
                d.data.append(DATAITEM(self.v!=other.data[i].value, other.data[i].date))
            d.isvector = 1
            return d
        else:
            for i in range(0, len(other.data)):
                #d.data.append(self.data[i] != other.data[i])
                d.data.append(DATAITEM(self.data[i].value != other.data[i].value, self.data[i].date))
            d.isvector = 1
            return d
    
    def __neg__(self):
        d = MYDATA()
        d.data = []
        
        if self.isvector == 1:
            for i in self.data:
                d.data.append(DATAITEM(-(i.value), i.date))

            d.isvector = 1
        else:
            d.v = -self.v
            d.isvector = 0

        return d

#tlow = MYDATA()
#tlow.isvector = 1
tlow = [DATAITEM(1, 20110301), DATAITEM(2, 20110302), DATAITEM(3, 20110303)]

#thigh = MYDATA()
#thigh.isvector = 1
thigh = [DATAITEM(4, 20110301), DATAITEM(5, 20110302), DATAITEM(5, 20110303)]


#topen = MYDATA()
#topen.isvector = 1
topen = [DATAITEM(7, 20110301), DATAITEM(8, 20110302), DATAITEM(9, 20110303)]

#tclose = MYDATA()
#tclose.isvector = 1
tclose = [DATAITEM(10, 20110301), DATAITEM(11, 20110302), DATAITEM(12, 20110303)]

#tvloumn = MYDATA()
#tvloumn.isvector = 1
tvloumn = [DATAITEM(13, 20110301), DATAITEM(14, 20110302), DATAITEM(15, 20110303)]

tl = MYDATA()
tl.isvector = 0
tl.v = 1

th = MYDATA()
th.isvector = 0
th.v = 2

to = MYDATA()
to.isvector = 0
to.v = 3

tc = MYDATA()
tc.isvector = 0
tc.v = 4

tv = MYDATA()
tv.isvector = 0
tv.v = 5


class Parser(object):
    """
    Base class for a lexer/parser that has the rules defined as methods
    """
    tokens = ()
    precedence = ()

    def __init__(self, **kw):
        #self.debug = kw.get('debug', 0)
        #self.stockid = kw.get('stockid', '0')
        self.names = {}        
        self.varibles ={}
        
        try:
            modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__
        except:
            modname = "parser"+"_"+self.__class__.__name__
        #self.debugfile = modname + ".dbg"
        self.tabmodule = modname + "_" + "parsetab"
        #print self.debugfile, self.tabmodule
        
        # Build the lexer and parser
        lex.lex(module=self)
        yacc.yacc(module=self, debug=0,tabmodule=self.tabmodule)

    def run(self):
        while 1:
            try:
                s = raw_input()
            except EOFError:
                break
            if not s: continue     
            yacc.parse(s)
            
        #yacc.parse("a=100+HIGH")
        return self.names

    def run2(self):
        yacc.parse("a=200")
        return self.names['a']

    def run3(self):
        yacc.parse("a")
        return self.names['a']

    def run4(self):
        yacc.parse("b=LOW+100")
        yacc.parse("c=b+1")
        return self.names

    def parse(self, script):
        try:
            yacc.parse(script)
        except:
            print "error"

        return self.names

class ScriptEngine(Parser):
    
    keywords = (
        "SELECTBYDATE", "SELECTBYCOND","COUNT", "NDAY", "REF", "REFDATE",
        "CROSS",
        "MA",
        "HIGH", "LOW", "OPEN", "CLOSE", "VOLUMN",
        "H", "L", "O", "C", "V"
    )

    tokens = keywords + (
        'COMMA',
        'NAME','FCONST', 'ICONST',
        'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
        'DEFINES',
        'LT', 'LE', 'GT', 'GE', 'NE', 'EE',
        'LPAREN','RPAREN'
        )

    # Tokens
    t_DEFINES = r':='
    
    t_COMMA   = r'\,'

    t_PLUS    = r'\+'
    t_MINUS   = r'-'
    t_TIMES   = r'\*'
    t_DIVIDE  = r'/'
    t_EQUALS  = r'='
    t_LPAREN  = r'\('
    t_RPAREN  = r'\)'

    #t_SELECTBYDATE = r'SELECTBYDATE'
    #t_MA      = r'MA'

    #t_HIGH    = r'HIGH'
    #t_LOW     = r'LOW'
    #t_OPEN    = r'OPEN'
    #t_CLOSE   = r'CLOSE'
    #t_VOLUMN  = r'VOLUMN'

    t_LT      = r'<'
    t_LE      = r'<='
    t_GT      = r'>'
    t_GE      = r'>='
    t_NE      = r'!='
    t_EE      = r'=='

    t_NAME    = r'[a-zA-Z_][a-zA-Z0-9_]*'


    def handle_buildinf_ma(self, t):
        
        if(len(t[3]) == 2):
            vs = t[3][0]
            vn = t[3][1]

            #print vs.data, vn.v
            if vn.isvector == 1:
                print "wrong parameter for MA, now vector while int expected"
                return None
            if vs.isvector == 0:
                try:
                    d = MYDATA()
                    d.isvector = 0
                    d.v = vs.v / int(vn.v)
                except:
                    d = None

                t[0] = d
                return d
            try:
                d = MYDATA()
                d.isvector = 1
                d.data = []
                for i in range(0, len(vs.data)):
                    startd = 0
                    if i - int(vn.v) + 1> 0:
                        startd = i - int(vn.v) + 1

                    s = 0
                    for j in range(startd, i+1):
                        s += vs.data[j].value / (1.0*int(vn.v))
                    
                    d.data.append(DATAITEM(s, vs.data[i].date))
                t[0] = d
                return d
            except Exception, ex:
                print "wrong parameter for MA" + str(ex)
        else:
            print "wrong parameters for MA, expected MA(V, N)"

    def handle_buildinf_nday(self, t):
        if len(t[3]) == 2:
            vindex = t[3][0]
            vnum   = t[3][1]

            if vindex.isvector == 0:
                print "illegal paramters for count, number while vector expected"
                return
            try:
                startd = 0
                d = MYDATA()
                d.isvector = 0
                    
                if len(vindex.data) > vnum.v:
                    startd = len(vindex.data) - int(vnum.v)

                flag = 0                
                for i in range(startd, len(vindex.data)):
                    if not vindex.data[i].value:
                        flag = 1
                        break
                
                if not flag:
                    d.v = 1
                else:
                    d.v = 0
                
                t[0] = d                    
                return d                        
                                        
            except Exception, ex:
                print "illegal paramters for nday" + str(ex)
                    
    def handle_buildinf_count(self, t):
        if len(t[3]) == 2:

            vindex = t[3][0]
            vnum   = t[3][1]

            if vindex.isvector == 0:
                print "illegal paramters for count, number while vector expected"
                return
            try:
                startd = 0
                d = MYDATA()
                d.isvector = 0
                count = 0
                
                if len(vindex.data) > vnum.v:
                    startd = len(vindex.data) - int(vnum.v)

                for i in range(startd, len(vindex.data)):
                    if vindex.data[i].value:
                        count += 1

                d.v = count                
                t[0] = d
                return d                
                        
            except Exception, ex:
                print "illegal paramters for count" + str(ex)
        else:
            print "wrong paramters for count, expected selectbydate(V, N)"

    def handle_buildinf_refdate(self, t):
        if len(t[3]) == 2:
            vindex = t[3][0]
            vdate   = t[3][1]

            if vindex.isvector == 0:
                print "illegal paramters for count, number while vector expected"
                return
            try:
                startd = 0
                d= MYDATA()
                d.isvector = 0

                lo = 0
                hi = len(vindex.data) - 1
                index = -1               
                while (lo <= hi):
                    mid = (lo + hi)/2
                    if vindex.data[mid].date < int(vdate.v) :
                        lo = mid + 1
                    elif vindex.data[mid].date > int(vdate.v):
                        hi = mid - 1
                    else:
                        index = mid
                        break
                
                if index >= 0:
                    d.v = vindex.data[index].value
                    t[0] = d
                    return d
                
            except Exception, ex:
                print "illegal paramters for ref" + str(ex)
        else:
            print "wrong paramters for ref, expected selectbydate(V, date)"
        
    def handle_buildinf_ref(self, t):
        if len(t[3]) == 2:
            vindex = t[3][0]
            vnum   = t[3][1]

            if vindex.isvector == 0:
                print "illegal paramters for count, number while vector expected"
                return
            try:
                startd = 0
                d= MYDATA()
                d.isvector = 1
                d.data = []

                #if len(vindex.data) > vnum.v:
                #    startd = len(vindex.data) - int(vnum.v)
                days = int(vnum.v)
                for i in range(0, days):
                    d.data.append(DATAITEM(0, vindex.data[i].date))
                
                for i in range(days, len(vindex.data)):
                    d.data.append(DATAITEM(vindex.data[i-days].value, vindex.data[i].date))

                t[0] = d
                return d
            except Exception, ex:
                print "illegal paramters for ref" + str(ex)
        else:
            print "wrong paramters for ref, expected selectbydate(V, N)"

    def handle_buildinf_cross(self, t):
        if(len(t[3]) == 2):
            vindex1 = t[3][0]
            vindex2 = t[3][1]

            if vindex1.isvector == 0 or vindex2.isvector == 0:
                self.parameter_error("cross")
                return
            try:
                #print "cross"
                mind1 = int(vindex1.data[0].date)
                mind2 = int(vindex1.data[0].date)
                maxd1 = int(vindex2.data[-1].date)
                maxd2 = int(vindex2.data[-1].date)
                
                startd = max(mind1, mind2)
                endd   = min(maxd1, maxd2)

                s1=0
                s2=0
                for i in range(len(vindex1.data)):
                    if vindex1.data[i] == startd:
                        s1=i
                        break

                for i in range(len(vindex2.data)):
                    if vindex2.data[i] == endd:
                        s2=i
                        break
                e = min(len(vindex1.data), len(vindex2.data))

                flag = 0                
                while s1 < e and s2 < e:
                    #print s1, s2, e
                    if not (s1 + 1 < e and s2 + 1 < e):
                        flag = (vindex1.data[s1] == vindex2.data[s2])
                        break
                        
                    if (vindex1.data[s1].value - vindex2.data[s2].value)*(vindex1.data[s1+1].value - vindex2.data[s2+1].value) <= 0:
                        flag = 1
                        break
                    
                    s1 += 1
                    s2 += 2

                d = MYDATA()
                d.v = flag
                d.isvector = 0
                t[0] = d

                return d        
            except Exception, ex:
                self.parameter_error("cross")
        else:
            print "wrong paramters for selectbydate, expected cross(V1, V2)"

    def parameter_error(self, func):
        print "illegal paramters for "+str(func)+" number while vector expected"

    def handle_buildinf_selectbydate(self, t):
        #print str((len(t[3]))) + "#####"
        if(len(t[3]) == 3):
            #print t[3]

            vindex = t[3][0]
            vstartd = t[3][1]
            vendd   = t[3][2]

            if vindex.isvector == 0:
                print "illegal paramters for selectbydate number while vector expected"
                return
            try:
                sdate = int(vstartd.v)
                edate = int(vendd.v)

                if sdate <= 1990 or edate <= 1990 or edate < sdate:
                    print "out of range paramters for selectbydate"
                    return

                d = MYDATA()
                d.isvector = 1
                d.data = []
                for i in vindex.data:
                    if int(i.date) >= sdate and int(i.date) <= edate:
                        d.data.append(DATAITEM(i.value, int(i.date)))

                t[0] = d
                return d
                #print str(vindex) + " " + str(startd.v) + " " + str(endd.v)
            except Exception, ex:
                print "illegal paramters for selectbtdate" + str(ex)
            
        else:
            print "wrong paramters for selectbydate, expected selectbydate(V, start, end)"
    
    def handle_buildinf_selectbycond(self, t):
        if(len(t[3]) == 2):
            #print t[3]

            vindex = t[3][0]
            vcond = t[3][1]

            if (vindex.isvector + vcond.isvector == 1) :
                print "wrong parameters for selectbycond, should be both vector or number"
                return None

            if len(vindex.data) != len(vcond.data):
                print "vector should be same dimension"
                return None

            d = MYDATA()
            d.isvector = 1
            d.data = []
            for i in range(0, len(vindex.data)):
                if vcond.data[i].value == True:
                    d.data.append(vindex.data[i])

            t[0] = d
            return d
        else:
            print "wrong parameters for selectbycond, expected selectbycond(V, COND)"
            return None

    #t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'

    def t_MA(self, t):
        r'MA'
        return t

    def t_COUNT(self, t):
        r'COUNT'
        return t

    def t_NDAY(self, t):
        r'NDAY'
        return t

    def t_REFDATE(self, t):
        r'REFDATE'
        return t    

    def t_REF(self, t):
        r'REF'
        return t

    def t_CROSS(self, t):
        r'CROSS'
        return t
    
    def t_SELECTBYDATE(self, t):
        r'SELECTBYDATE'
        return t

    def t_SELECTBYCOND(self, t):
        r'SELECTBYCOND'
        return t
    
    def t_HIGH(self, t):
        r'HIGH'
        try:
            d = MYDATA()
            d.data = self.highlist
            d.isvector = 1
            
            t.value = d
        except:
            print "erro_t_high"
        return t

    def t_LOW(self, t):
        r'LOW'
        try:
            d = MYDATA()
            d.data = self.lowlist
            d.isvector = 1

            t.value = d
        except:
            print "erro_t_low"
        return t

    def t_OPEN(self, t):
        r'OPEN'
        try:
            d = MYDATA()
            d.data = self.openlist
            d.isvector = 1

            t.value = d
        except:
            print "error open"
        return t

    def t_CLOSE(self, t):
        r'CLOSE'
        try:
            d = MYDATA()
            d.data = self.closelist
            d.isvector = 1

            t.value = d
        except:
            print "error close"
        return t


    def t_VOLUMN(self, t):
        r'VOLUMN'
        try:
            d = MYDATA()
            d.data = self.volumn
            d.isvector = 1

            t.value = d
        except:
            print "error volumn"
        return t

    def t_H(self, t):
        r'H'
        try:
            t.value = th
        except:
            print "error h"
        return t


    def t_L(self, t):
        r'L'
        try:
            t.value = tl
        except:
            print "error l"
        return t


    def t_O(self, t):
        r'O'
        try:
            t.value = to
        except:
            print "error o"
        return t

    def t_C(self, t):
        r'C'
        try:
            t.value = tc
        except:
            print "error c"
        return t

    def t_V(self, t):
        r'V'
        try:
            t.value = tv
        except:
            print "error v"
        return t
        
    def t_FCONST(self, t):
        r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
        try:
            d = MYDATA()
            d.v = float(t.value)
            d.isvector = 0
            t.value = d
        except ValueError:
            print("Float value too large %s" % t.value)
            t.value = 0
        return t

    def t_ICONST(self, t):
        r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
        try:
            d = MYDATA()
            d.v = float(t.value)
            d.isvector = 0
            t.value = d
        except ValueError:
            print("Integer value too large %s" % t.value)
            t.value = 0
        return t

    t_ignore = " \t"

    def t_newline(self, t):
        r'\n+'
        t.lexer.lineno += t.value.count("\n")
        
    def t_error(self, t):
        print("Illegal character '%s'" % t.value[0])
        t.lexer.skip(1)



# Build the lexer
#import ply.lex as lex
#lex.lex(optimize=1)

# Parsing rules

    precedence = (
        ('left', 'LE', 'LT', 'GT', 'GE', 'NE', 'EE'),
        ('left','PLUS','MINUS'),
        ('left','TIMES','DIVIDE'),
        ('right','UMINUS'),
        )

    # dictionary of names
    #names = { }


    def p_statement_assign(self, t):
        'statement : NAME EQUALS expression'
        self.names[t[1]] = t[3]

    def p_statement_define(self, t):
        'statement : NAME DEFINES expression'
        self.varibles[t[1]] = t[3]

    def p_statement_expr(self, t):
        'statement : expression'
        if t[1]:
            if t[1].isvector == 0:
                print(t[1].v)
            else:
                print(t[1].data)

    def p_paramlist(self, t):
        '''paramlist : paramlist COMMA pitem
                     | pitem'''
        #print str(t[1]) + "--------------" + str(len(t))
        #print str(t[3].v)

        params = {}
        if len(t) == 2:
            params[0] = t[1]
            t[0] = params
            
        elif len(t) >= 2:
            #print str(t[3])  + "$$"
            j = len(t[1])

            t[1][j] = t[3]
            
            #for i in range(3, len(t), 2):
            #    t[1][j] = t[i] 
            #    j += 1

            t[0] = t[1]
        else:
            print "wrong paramter list"
        
        
        #print "PARAM"

    def p_pitem(self, t):
        '''pitem : expression'''
        #for i in t:
            #print i
        #print "pitem"
        t[0] = t[1]

    def p_bfname(self, t):
        '''bfname : MA
                  | COUNT
                  | NDAY
                  | REF
                  | REFDATE
                  | SELECTBYDATE
                  | SELECTBYCOND
                  | CROSS'''

        t[0] = t[1]
        
    def p_buildinfunction(self, t):
        '''pbuildinfunc : bfname LPAREN paramlist RPAREN
                        | bfname LPAREN RPAREN'''

        #print "Function"
        #print str(t[1]) + "---------"

        try:
            self.func_table[t[1]](t)
        except Exception, ex:
            print "error call " + str(t[1]) + " "+ str(ex)
        

    def p_expression_binop(self, t):
        '''expression : expression PLUS expression
                      | expression MINUS expression
                      | expression TIMES expression
                      | expression DIVIDE expression
                      | expression LT expression
                      | expression LE expression
                      | expression GT expression
                      | expression GE expression
                      | expression EE expression
                      | expression NE expression
                      | pbuildinfunc'''
        
        #print str(len(t)) + "------------"
        #for i in t:
            #print str(i)+"$"
        #print
        if len(t) <= 2:
            t[0] = t[1]
            return

        if t[2] == '+'   : t[0] = t[1] + t[3]
        elif t[2] == '-' : t[0] = t[1] - t[3]
        elif t[2] == '*' : t[0] = t[1] * t[3]
        elif t[2] == '/' : t[0] = t[1] / t[3]

        elif t[2] == '<' : t[0] = (t[1] <  t[3])
        elif t[2] == '>' : t[0] = (t[1] >  t[3])
        elif t[2] == '>=': t[0] = (t[1] >= t[3])
        elif t[2] == '<=': t[0] = (t[1] <= t[3])
        elif t[2] == '==': t[0] = (t[1] == t[3])
        elif t[2] == '!=': t[0] = (t[1] != t[3])

    def p_expression_uminus(self, t):
        'expression : MINUS expression %prec UMINUS'
        t[0] = -t[2]

    def p_expression_group(self, t):
        'expression : LPAREN expression RPAREN'
        t[0] = copy.deepcopy(t[2])

    def p_expression_fconst(self, t):
        'expression : FCONST'
        t[0] = copy.deepcopy(t[1])

    def p_expression_iconst(self, t):
        'expression : ICONST'
        t[0] = copy.deepcopy(t[1])

    def p_expression_buildin(self, t):
        '''expression : HIGH
                      | LOW
                      | OPEN
                      | CLOSE
                      | VOLUMN
                      | H
                      | L
                      | O
                      | C
                      | V'''
        t[0] = t[1]
        #print "reserverd words"
        
    def p_expression_name(self, t):
        'expression : NAME'
        try:
            t[0] = copy.deepcopy(self.names[t[1]])
        except LookupError:
            print("Undefined name '%s'" % t[1])
            t[0] = None

    def p_error(self, t):
        if t:
            print("Syntax error at '%s'" % t.value)
        else:
            print("Syntax error at EOF")


    def __init__(self, **kw):
        self.stockid = kw.get('stockid', '0')
        
        self.func_table = {'MA':self.handle_buildinf_ma,
                           'SELECTBYDATE': self.handle_buildinf_selectbydate,
                           'SELECTBYCOND': self.handle_buildinf_selectbycond,
                           'COUNT'       : self.handle_buildinf_count,
                           'NDAY'        : self.handle_buildinf_nday,
                           'REF'         : self.handle_buildinf_ref,
                           'REFDATE'     : self.handle_buildinf_refdate,
                           'CROSS'       : self.handle_buildinf_cross}
        
        
        self.openlist =  kw.get('openlist', [])
        self.highlist =  kw.get('highlist', [])
        self.lowlist =   kw.get('lowlist',  [])
        self.closelist = kw.get('closelist', [])
        self.volumn =  kw.get('volumn', [])
        self.adjclose = kw.get('adjclose', [])
        
        super(self.__class__, self).__init__()
        
#import ply.yacc as yacc
#yacc.yacc(optimize=0)
    

#while 1:
#    try:
#        s = raw_input('calc > ')
#    except EOFError:
#        break
#    yacc.parse(s)

if __name__ == '__main__':
    c=ScriptEngine(stockid='601117')
    print c.stockid
    c.run()
